#include "../include/head.h"
#include "../include/func.h"

int main(int argc, char *argv[]){                                  
    ARGS_CHECK(argc, 2);

    // 从bin下的配置文件拿到服务器的ip和port
    char server_ip[16] = "";
    char server_port[6] = "";
    conf_get(argv[1], server_ip, server_port);

    // 与服务器建立tcp连接
    socket_t sockfd = tcp_connect(server_ip, server_port);

    // 初始化一个小火车
    Train_t train = {0};
    if (user_login(sockfd, &train) == -1) {
        printf("登陆失败，用户名或密码错误！\n");
        return -1;
    }

    printf("登录成功！现在你可以输入命令了。\n");

    char buf[4096] = {0};
    Cmd_t cmd = {0};

    while (1) {
        memset(&train, 0, sizeof(Train_t));
        memset(&cmd, 0, sizeof(Cmd_t));
        memset(buf, 0, sizeof(buf));

        // 从stdin读取命令
        read(STDIN_FILENO, buf, sizeof(buf));
        buf[strlen(buf) - 1] = '\0';

        if (!strcmp(buf, "quit")) {
            exit(EXIT_FAILURE);
        }

        // 检查命令是否合法
        init_cmd(buf, &cmd);
        cmd_check(&cmd);

        // 设置小火车的头和车厢
        memcpy(train._data, &cmd, sizeof(cmd));
        train._data_len = sizeof(cmd);
        send(sockfd, &train, sizeof(int) + train._data_len, 0);

        if (!strncmp("ls", cmd._cmd[0], 2)) {
            while (1) {
                recv(sockfd, &train._data_len, sizeof(int), MSG_WAITALL);
                if (0 == train._data_len) { //收到0，命令结束
                    break;
                }
                recv(sockfd, train._data, train._data_len, MSG_WAITALL);
                printf("%s\n", train._data);
            }
        } else if (!strncmp("puts", cmd._cmd[0], 4)) {
            //上传文件
            int ret = -1;

            //检查文件是否存在，且是否是常规文件
            off_t filesize = 0;
            struct stat st;
            //stat 函数用于获取文件或目录的元信息
            stat(cmd._cmd[1], &st);
            filesize = st.st_size;
            printf("filesize = %ld\n", filesize);

            //如果文件不是常规文件，将文件大小设为0
            if (filesize && S_IFREG != (st.st_mode & S_IFMT)) {
                filesize = 0;
            }
            printf("filesize = %ld\n", filesize);
            //发送文件大小，让服务器选择接收方式
            send(sockfd, &filesize, sizeof(int), 0);

            if (0 == filesize) {
                //没找着这个常规文件
                printf("Not found the file!\n");
                return -1;
            } else if (filesize > HUNDRED_MEGABYTE) {
                ret = send_file_sendfile(sockfd, cmd._cmd[1], filesize); //大于100M, 用零拷贝接口
            } else {
                printf("send_file_train\n");
                ret = send_file_train(sockfd, cmd._cmd[1]);//用普通方式发送
            }
            printf("ret = %d\n",ret);
            //判断传输结果
            if (-2 == ret) {
                //服务器异常断开, 退出
                printf("server erupt!\n");
                return -1;
            }
            //传输完成，接收传输结果
            recv(sockfd, &train._data_len, sizeof(int), MSG_WAITALL);
            recv(sockfd, train._data, train._data_len, MSG_WAITALL);
            printf("%s\n", train._data);
        } else if (!strncmp("gets", cmd._cmd[0], 4)) {
            //下载文件
            int ret = -1;

            //先接文件大小
            int filesize = 0;
            recv(sockfd, &filesize, sizeof(int), MSG_WAITALL);
            printf("filesize = %d\n", filesize);

            if (0 == filesize) {
                //文件不存在
                printf("Not found the file!\n");
                continue;
            } else if (filesize > HUNDRED_MEGABYTE) {
                ret = recv_file_mmap(sockfd, cmd._cmd[1], filesize);
            } else {
                ret = recv_file_train(sockfd, cmd._cmd[1]);
            }

            //判断传输结果
            if (-2 == ret) {
                //服务器异常断开
                printf("server erupt!\n");
                return -1;
            }
            //传输完成，接收传输结果
            recv(sockfd, &train._data_len, sizeof(int), MSG_WAITALL);
            recv(sockfd, train._data, train._data_len, MSG_WAITALL);
            printf("%s\n", train._data);
        } else {
            //其他命令
            //先接命令结果长度，后接命令结果
            recv(sockfd, &train._data_len, sizeof(int), MSG_WAITALL);
            recv(sockfd, train._data, train._data_len, MSG_WAITALL);
            printf("%s\n", train._data);
        }
    }

    return 0;
}

